/**
 * 数组中的逆序对
 * 
 * 1,2,3,4,5,6,7,0
 * 
 * 描述

在数组中的两个数字，如果前面一个数字大于后面的数字，则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007

数据范围：  对于 
50
%
50% 的数据, 
s
i
z
e
≤
1
0
4
size≤10 
4
 
对于 
100
%
100% 的数据, 
s
i
z
e
≤
1
0
5
size≤10 
5
 
数组中所有数字的值满足 
0
≤
v
a
l
≤
1
0
9
0≤val≤10 
9
 

要求：空间复杂度 
O
(
n
)
O(n)，时间复杂度 
O
(
n
l
o
g
n
)
O(nlogn)
输入描述：

题目保证输入的数组中没有的相同的数字
 * 
 */
public class 数组中的逆序对 {
    
    public static void main(String[] args) {
        
        int[] nums = new int[]{1,2,3,4,5,6,7,0};

        int result = InversePairs(nums);
        System.out.println(result);

    }

    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     * 
     * @param nums int整型一维数组 
     * @return int整型
     */
    public static int InversePairs (int[] nums) {
        // write code here

        if (nums == null || nums.length <= 1) {
            return 0;
        }

        MergeSort(nums, 0, nums.length-1);
        return cnt;
    }

    private static int cnt;
    private static void MergeSort(int[] array, int start, int end){
        if(start>=end)return;
        int mid = (start+end)/2;
        MergeSort(array, start, mid);
        MergeSort(array, mid+1, end);
        MergeOne(array, start, mid, end);
    }
    private static void MergeOne(int[] array, int start, int mid, int end){
        int[] temp = new int[end-start+1];
        int k=0,i=start,j=mid+1;
        while(i<=mid && j<= end){
//如果前面的元素小于后面的不能构成逆序对
            if(array[i] <= array[j])
                temp[k++] = array[i++];
            else{
//如果前面的元素大于后面的，那么在前面元素之后的元素都能和后面的元素构成逆序对
                temp[k++] = array[j++];
                cnt = (cnt + (mid-i+1))%1000000007;
            }
        }
        while(i<= mid)
            temp[k++] = array[i++];
        while(j<=end)
            temp[k++] = array[j++];
        for(int l=0; l<k; l++){
            array[start+l] = temp[l];
        }
    }
}
